home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
debugnub
/
RDTRuntime.c
< prev
Wrap
C/C++ Source or Header
|
1992-02-18
|
13KB
|
610 lines
/* begincopyright
Copyright (c) 1988 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA 94304
endcopyright */
/*
* RDTRuntime.c
*
* Runtime support for remote debug tool.
*
* Demers, February 19, 1990 9:53:45 am PST
*/
#include "xr/BasicTypes.h"
#include "xr/Errno.h"
#include "xr/CirioNubTypes.h"
#include "xr/CirioNubProtocol.h"
#include "xr/RDTRuntime.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
/*
read/write without returning short result
*/
static CirioNubRetCode
RDT_DoIOUntilDone(fd, in, buf, nBytes)
int fd;
bool in;
char *buf;
int nBytes;
{
int ans;
CirioNubRetCode retCode = cnrc_comm;
for(;;) {
if( fd < 0 ) break;
ans = (in ? read(fd, buf, nBytes) : write(fd, buf, nBytes));
if( ans < 0 ) { ans = (-errno); break; }
if( (ans == 0) && in ) break;
nBytes -= ans;
buf += ans;
if( nBytes <= 0 ) { retCode = cnrc_ok; break; }
}
return retCode;
}
#define readall(fd, buf, nBytes) \
RDT_DoIOUntilDone((fd), TRUE, (buf), (nBytes))
#define writeall(fd, buf, nBytes) \
RDT_DoIOUntilDone((fd), FALSE, (buf), (nBytes))
/*
* Global state
*/
int RDT_rpcFD = -1;
int RDT_dbPrintCtl = 1;
/* positive disables until counts down to 1 */
/* negative enables until counts up to 0 */
/*
* Debugging messages
*/
void RDT_Msg(fmt, x1, x2, x3, x4)
char *fmt;
int x1, x2, x3, x4;
{
char buf[1024];
sprintf(buf, fmt, x1, x2, x3, x4);
(void)RDT_DoIOUntilDone(1, FALSE, buf, strlen(buf));
}
void RDT_DBMsg(fmt, x1, x2, x3, x4)
char *fmt;
int x1, x2, x3, x4;
{
char buf[1024];
int ctl = RDT_dbPrintCtl;
if( (ctl < 0) || (ctl == 1) ) {
sprintf(buf, fmt, x1, x2, x3, x4);
(void)RDT_DoIOUntilDone(1, FALSE, buf, strlen(buf));
}
if( ctl < 0 ) {
ctl++;
} else if( ctl > 1 ) {
ctl--;;
}
RDT_dbPrintCtl = ctl;
}
/*
* Marshalling stuff
*/
/*
* Send data with type info
*/
static CirioNubRetCode
RDT_Put32Inner(n, tag)
unsigned n;
enum CirioNubTag tag;
{
struct {
struct CirioNubWrapper w;
net_long x;
} buf;
buf.w.cnw_tag = htons(((short)(tag)));
buf.w.cnw_len = htons( (sizeof n) );
buf.x = htonl(n);
return writeall(RDT_rpcFD, &buf, (sizeof buf));
}
CirioNubRetCode
RDT_PutRetCode(c)
CirioNubRetCode c;
{
return RDT_Put32Inner(((unsigned)(c)), cnt_retCode);
}
CirioNubRetCode
RDT_PutProcID(id)
unsigned id;
{
return RDT_Put32Inner(((unsigned)(id)), cnt_procID);
}
CirioNubRetCode
RDT_PutCard32(n)
unsigned n;
{
return RDT_Put32Inner(((unsigned)(n)), cnt_card32);
}
CirioNubRetCode
RDT_PutInt32(n)
int n;
{
return RDT_Put32Inner(((unsigned)(n)), cnt_int32);
}
static CirioNubRetCode
RDT_PutBlock8Inner(b, len, tag)
char *b;
int len;
enum CirioNubTag tag;
{
struct CirioNubWrapper w;
CirioNubRetCode ans;
w.cnw_tag = htons(((short)(tag)));
w.cnw_len = htons(len);
if( (ans = writeall(RDT_rpcFD, &w, (sizeof w))) != cnrc_ok ) {
return(ans);
}
if( len == 0 ) return(cnrc_ok);
if( (ans = writeall(RDT_rpcFD, b, len)) != cnrc_ok ) {
return(ans);
}
if( len & 03 ) {
int slop = 4 - (len & 03);
int zero = 0;
if( (ans = writeall(RDT_rpcFD, &zero, slop)) != cnrc_ok ) {
return(ans);
}
}
return(cnrc_ok);
}
CirioNubRetCode
RDT_PutString(s)
char *s;
{
return( RDT_PutBlock8Inner(s, strlen(s), cnt_string) );
}
CirioNubRetCode
RDT_PutBlock8(b, len)
char *b;
int len;
{
return( RDT_PutBlock8Inner(b, len, cnt_block8) );
}
CirioNubRetCode
RDT_PutBlock16(b, len)
short *b;
int len;
{
struct CirioNubWrapper w;
CirioNubRetCode ans;
int zero = 0;
b = (short *)(((unsigned)(b)) & (~01));
len = (len + 1) & (~01);
w.cnw_tag = htons(cnt_block16);
w.cnw_len = htons(len);
ans = writeall(RDT_rpcFD, &w, (sizeof w));
if( (ans = writeall(RDT_rpcFD, &w, (sizeof w))) != cnrc_ok ) {
return(ans);
}
if( len == 0 ) return(cnrc_ok);
if( htons(1) != 1 ) {
int cnt = len;
short *p = b;
while( cnt > 0 ) { *p = htons(*p); p++; cnt-= 2; }
}
if( (ans = writeall(RDT_rpcFD, b, len)) == cnrc_ok ) {
if( (len & 03) != 0 ) {
ans = writeall(RDT_rpcFD, &zero, 2);
}
}
if( htons(1) != 1 ) {
int cnt = len;
short *p = b;
while( cnt > 0 ) { *p = ntohs(*p); p++; cnt-= 2; }
}
return( ans );
}
CirioNubRetCode
RDT_PutBlock32(b, len)
long *b;
int len;
{
struct CirioNubWrapper w;
CirioNubRetCode ans;
b = (long *)(((unsigned)(b)) & (~03));
len = (len + 3) & (~03);
w.cnw_tag = htons(cnt_block32);
w.cnw_len = htons(len);
if( (ans = writeall(RDT_rpcFD, &w, (sizeof w))) != cnrc_ok ) {
return(ans);
}
if( len == 0 ) return(cnrc_ok);
if( htons(1) != 1 ) {
int cnt = len;
long *p = b;
while( cnt > 0 ) { *p = htonl(*p); p++; cnt-= 4; }
}
ans = writeall(RDT_rpcFD, b, len);
if( htons(1) != 1 ) {
int cnt = len;
long *p = b;
while( cnt > 0 ) { *p = ntohl(*p); p++; cnt-= 4; }
}
return( ans );
}
static CirioNubRetCode
RDT_GetCard32(b)
unsigned *b;
{
CirioNubRetCode ans;
unsigned buf;
if( (ans = readall(RDT_rpcFD, &buf, (sizeof buf))) != cnrc_ok )
return(ans);
*b = ntohl(buf);
return(cnrc_ok);
}
#define RDT_GetInt32(b) RDT_GetCard32( ((unsigned *)(b)) )
#define RDT_GetRetCode(b) RDT_GetCard32( ((unsigned *)(b)) )
#define RDT_GetProcID(b) RDT_GetCard32( ((unsigned *)(b)) )
/* all lengths below are rounded up to full 32-bit words */
static CirioNubRetCode
RDT_GetBlock8(b, len)
char *b;
int len;
{
len = (len + 3) & (~03);
return( readall(RDT_rpcFD, b, len) );
}
static CirioNubRetCode
RDT_GetBlock16(b, len)
short *b;
int len;
{
CirioNubRetCode ans;
if( len == 0 ) return(cnrc_ok);
b = (short *)(((unsigned)(b)) & (~01));
len = (len + 3) & (~03);
if( (ans = readall(RDT_rpcFD, b, len)) != cnrc_ok ) return(ans);
if( htons(1) != 1 ) {
while( len > 0 ) { *b = ntohs(*b); b++; len -= 2; }
}
return(cnrc_ok);
}
static CirioNubRetCode
RDT_GetBlock32(b, len)
long *b;
int len;
{
CirioNubRetCode ans;
if( len == 0 ) return(cnrc_ok);
b = (long *)(((unsigned)(b)) & (~03));
len = (len + 3) & (~03);
if( (ans = readall(RDT_rpcFD, b, len)) != cnrc_ok ) return(ans);
if( htonl(1) != 1 ) {
while( len > 0 ) { *b = ntohl(*b); b++; len -= 4; }
}
return(cnrc_ok);
}
CirioNubRetCode
RDT_ReadReply(buffer, bufferBytes, argcPtr)
unsigned *buffer;
unsigned bufferBytes;
unsigned *argcPtr;
{
CirioNubRetCode ans;
CirioNubRetCode retCode;
struct CirioNubWrapper w;
int len, roundedLen, roundedLenWithNull;
char *p;
unsigned *argp;
# define NEEDSPACE(n) \
if ( (((char *)(argp)) + (n)) > p ) { ans = cnrc_space; goto Out; }
*argcPtr = 0; /* default */
argp = buffer;
p = ((char *)(buffer)) + bufferBytes;
for(;;) {
if( (ans = readall(RDT_rpcFD, &w, (sizeof w))) != cnrc_ok ) {
RDT_Msg("Bad read %d\n", ans);
goto Out;
}
len = (int)(ntohs(w.cnw_len));
roundedLen = (len + 03) & (~03);
switch( ntohs(w.cnw_tag) ) {
case cnt_retCode:
if( (ans = RDT_GetRetCode(&retCode)) == cnrc_ok ) {
(*argcPtr) = (argp - buffer);
}
goto Out;
case cnt_card32:
NEEDSPACE((sizeof *argp));
if( (ans = RDT_GetCard32(argp)) != cnrc_ok ) goto Out;
argp++;
break;
case cnt_int32:
NEEDSPACE((sizeof *argp));
if( (ans = RDT_GetInt32(argp)) != cnrc_ok ) goto Out;
argp++;
break;
case cnt_string:
roundedLenWithNull = (len + 04) & (~03);
NEEDSPACE(roundedLenWithNull+(sizeof *argp));
p -= roundedLenWithNull;
if( (ans = RDT_GetBlock8(p, roundedLen)) != cnrc_ok )
goto Out;
p[len] = 0;
*argp++ = (unsigned)(p);
break;
case cnt_block8:
NEEDSPACE(roundedLen+2*(sizeof *argp));
p -= roundedLen;
if( (ans = RDT_GetBlock8(p, roundedLen)) != cnrc_ok )
goto Out;
*argp++ = len;
*argp++ = (unsigned)(p);
break;
case cnt_block16:
NEEDSPACE(roundedLen+2*(sizeof *argp));
p -= roundedLen;
if( (ans = RDT_GetBlock16(p, roundedLen)) != cnrc_ok )
goto Out;
*argp++ = len;
*argp++ = (unsigned)(p);
break;
case cnt_block32:
NEEDSPACE(roundedLen+2*(sizeof *argp));
p -= roundedLen;
if( (ans = RDT_GetBlock32(p, roundedLen)) != cnrc_ok )
goto Out;
*argp++ = len;
*argp++ = (unsigned)(p);
break;
default:
ans = cnrc_protocol;
goto Out;
}
}
Out:
if( ans >= cnrc_MUST_CLOSE_CONNECTION ) {
(void) RDT_Disconnect(FALSE);
}
return ans;
}
#undef NEEDSPACE
CirioNubRetCode
RDT_SendCall(procID)
unsigned procID;
{
CirioNubRetCode ans;
ans = RDT_PutProcID(procID);
if( ans >= cnrc_MUST_CLOSE_CONNECTION ) {
(void) RDT_Disconnect(FALSE);
}
return ans;
}
static int /* -err */
RDT_ParseNumericAddressAndPort( ap, name, port )
struct sockaddr_in *ap;
char *name;
unsigned port;
{
int i, j;
char c;
u_int v;
u_char b[4];
i = 0;
j = 0;
while ((c=name[i])!=0) {
v = 0;
if (c=='.') {return(-1);}
while ((c!='.')&&(c!=0)) {
if (c < '0') {return(-1);}
if (c > '9') {return(-1);}
v = (v * 10) + (c-'0');
if (v > 255) {return(-1);}
i=i+1;
c=name[i];
}
if (j>=4) {return(-1);}
b[j] = v;
j = j+1;
if (c!=0) {i=i+1;}
}
if( port == 0 ) port = CIRIO_NUB_LISTENER_PORT;
if (j!=4) {return(-1);}
bzero( ((char *)(ap)), (sizeof (*ap)) );
ap->sin_family = AF_INET;
ap->sin_port = port;
bcopy( b, ((char *)(&(ap->sin_addr))), 4);
return (0); /* success */
}
#ifdef UNDEFINED
static int /* -err */
RDT_ParseNameAndPort( ap, name, port )
struct sockaddr_in *ap;
char *name;
unsigned port;
{
extern struct hostent *(gethostbyname());
extern char *(strrchr());
struct hostent *hep;
char *colonPtr;
int len, tPort;
int ans = 0;
char *fixedName = name;
colonPtr = strrchr( name, ':' );
if( colonPtr != NIL ) {
len = (colonPtr - name);
fixedName = (char *) malloc(1+len);
(void) bcopy( name, fixedName, len);
fixedName[len] = 0;
tPort = atoi(&(colonPtr[1]));
if( tPort == -1 ) { ans = -1; goto Out; }
if( tPort > 0 ) port = ((unsigned)(tPort));
}
if( port == 0 ) port = CIRIO_NUB_LISTENER_PORT;
hep = gethostbyname(fixedName);
if( hep == 0 ) { ans = -2; goto Out; }
if( hep->h_addrtype != AF_INET ) { ans = -3; goto Out; }
bzero( ((char *)(ap)), (sizeof (*ap)) );
ap->sin_family = hep->h_addrtype;
ap->sin_port = ((u_short)(port));
bcopy( ((char *)(hep->h_addr)), ((char *)(&(ap->sin_addr))),
hep->h_length );
Out:
if( fixedName != name ) free(fixedName);
return ans;
}
#else
static int /* -err */
RDT_ParseNameAndPort( ap, name, port )
struct sockaddr_in *ap;
char *name;
unsigned port;
{
extern struct hostent *(gethostbyname());
struct hostent *hep;
int tPort;
int ans = 0;
if( port == 0 ) port = CIRIO_NUB_LISTENER_PORT;
hep = gethostbyname(name);
if( hep == 0 ) { ans = -2; goto Out; }
if( hep->h_addrtype != AF_INET ) { ans = -3; goto Out; }
bzero( ((char *)(ap)), (sizeof (*ap)) );
ap->sin_family = hep->h_addrtype;
ap->sin_port = ((u_short)(port));
bcopy( ((char *)(hep->h_addr)), ((char *)(&(ap->sin_addr))),
hep->h_length );
Out:
return ans;
}
#endif
CirioNubRetCode
RDT_Connect(hostName, defaultPort)
char *hostName;
unsigned defaultPort;
{
unsigned addrBuf[32];
struct sockaddr_in a;
int fd;
int ans;
int one = 1;
if( (RDT_ParseNumericAddressAndPort(&a, hostName, defaultPort) < 0)
&& (RDT_ParseNameAndPort(&a, hostName, defaultPort) < 0) ) {
return cnrc_badArgs;
}
fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if( fd < 0 )
return cnrc_comm;
ans = connect(fd, &a, (sizeof a));
if( ans < 0 ) {
(void)close(fd);
return cnrc_comm;
}
(void) setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, (sizeof one));
RDT_rpcFD = fd;
return cnrc_ok;
}
CirioNubRetCode
RDT_Disconnect( doAbort )
bool doAbort;
{
if( RDT_rpcFD < 0 ) return cnrc_ok;
if( doAbort ) {
(void) shutdown(RDT_rpcFD);
}
(void) close(RDT_rpcFD);
RDT_rpcFD = -1;
return cnrc_ok;
}